% $Id: Stop.m 3 2008-11-12 15:25:19Z Jie.Bao $

classdef Stop
%STOPS2 Summary of this class goes here
%   Detailed explanation goes here

   properties
       H = [];
       hPos = [];
       hNeg = [];
       X;
       Y;
       Radius = 3;
       TotalSweep =0;
       Range = 0;
       Min;
       Max;
       Begin
       End
   end

   methods
       function this = Stop(x,y,h)
          this.H = h;
          this.X = x;
          this.Y = y;
          this.Begin = h(1);
          this.End = h(length(h));
          for j=1:length(h)
              if h(j)< 0
                  this.hNeg(length(this.hNeg)+1) = h(j);
              elseif h(j) >=0
                  this.hPos(length(this.hPos)+1) = h(j);
              end
          end  
          
          angle_sum = 0;
          previous_angle = h(1);
          for j=2:length(h)
              current_angle = h(j);
              if (previous_angle <-170 && current_angle > 170) || ...
                 (previous_angle > 170 && current_angle < -170 )
                    angle_sum = angle_sum + (180-abs(previous_angle)) + (180-abs(current_angle));
              elseif (previous_angle < 15 && previous_angle >0 && ...
                  current_angle >-15 && current_angle < 0 ) || ...
                 (previous_angle > -15 && previous_angle <0 && ...
                  current_angle <15 && current_angle > 0 ) 
                    angle_sum = angle_sum + abs(previous_angle) + abs(current_angle);
              else
                    angle_sum = angle_sum + abs(current_angle - previous_angle);
              end
              previous_angle = current_angle;
          end
          this.TotalSweep = angle_sum;
          
           if isempty(min(this.hNeg)) || isempty(max(this.hNeg))
               this.Min = min(this.hPos);
               this.Max = max(this.hPos);
           elseif isempty(min(this.hPos)) || isempty(max(this.hPos))
               this.Min = min(this.hNeg);
               this.Max = max(this.hNeg);
           elseif min(this.hPos) < 10 && max(this.hPos) > 170
               
               
               
           else
               if (min(this.hPos) <10 && max(this.hNeg) >-10)
                   this.Max = max(this.hPos);
                   this.Min = min(this.hNeg);
               else
                   this.Max = min(this.hPos);
                   this.Min = max(this.hNeg);
               end
           end
            
           
           this.Range = this.GetRange();
       end
       
       function r = GetRange(this)
           r=0;
           %There is no rotation really unless they did 1 exact circle, and
           %stopped at the exact same angle. omiting that as a
           %impossibility
           if this.Min == this.Max
               r = 0;
               return
           end
           
           %2 time stop, very small range
           if length(this.H) == 2
               r = min([this.Min-this.Max, 360-this.Min +this.Max]);
               return
           end
           
           
           %determine an intermediate point so we can find which way
           %rotation is
           med=0;
           for j=1:length(this.H)
              %no intermediate point found at all, very small range
              if(j == length(this.H))
                  r = this.Max-this.Min;
                  return
              end
              
              %this will work as intermedia point.
              if this.H(j) ~= this.Min && this.H(j) ~= this.Max
                  med = j;
                  break
              end
           end
            
           med
           
           if this.H(med) > this.Max || this.H(med) < this.Min
               r = 360 -this.Max + this.Min;
           else
               r = this.Max-this.Min;
           end
           
       end
       
           
       
       
       function out = IsUseful(this)
           out = 1;
           if this.TotalSweep <5
               out = 0;
           end
           
           
           range1 = abs(this.Min - this.Max);
           range2 = abs(360 - range1);
           %sweep = this.TotalSweep;
           if (( range1 < this.TotalSweep + 2) && ...
              ( range1 > this.TotalSweep - 2)) || ...
              (( range2 < this.TotalSweep + 2) && ...
              ( range2 > this.TotalSweep - 2))
              this.H;
              out =0;
           end
           
       end
       
       function [begin, endd, minn, maxx, total] = GetInfo(this)
           begin = this.Begin;
           endd = this.End;
           minn = this.Min;
           maxx = this.Max;
           total = this.TotalSweep;
       end
       
       function Plot(this)
           
           M = 0;
           m = 0;
           if isempty(min(this.hNeg)) || isempty(max(this.hNeg))
               arc(this.X, this.Y, min(this.hPos), max(this.hPos));
           
               m = min(this.hPos);
               M = max(this.hPos);
           elseif isempty(min(this.hPos)) || isempty(max(this.hPos))
               arc(this.X, this.Y, min(this.hNeg),max(this.hNeg));
               %2
               m = min(this.hNeg);
               M = max(this.hNeg);
           else
               if (min(this.hNeg) <-175)
                   arc(this.X, this.Y, -179.9, max(this.hNeg));
               else
                   arc(this.X, this.Y, min(this.hNeg), -0.1);
               end
               
               if (max(this.hPos) >175)
                   arc(this.X, this.Y, min(this.hPos), 179.9);
               else
                   arc(this.X, this.Y, .1, max(this.hPos));
               end
               %arc(this.X, this.Y, min(this.hNeg), max(this.hNeg));
               %arc(this.X, this.Y, min(this.hPos), max(this.hPos));
               %3
               if (min(this.hPos) <15 && max(this.hNeg) >-15)
                   m = max(this.hPos);
                   M = min(this.hNeg);
               else
                   m = min(this.hPos);
                   M = max(this.hNeg);
               end

           end
           offset = rand()*3 -1.5;
           line([this.X this.X+offset], [this.Y, this.Y+offset], 'Color', [0,1,0])
           text(this.X+offset, this.Y+offset,  ['[' int2str(m) ':' int2str(M) ']' '/' int2str(this.TotalSweep)]);
       end
   end
end 


function [ output_args ] = arc( x,y, begin_arc, end_arc )
    %ARC Summary of this function goes here
    %   Detailed explanation goes here
     if (begin_arc > -90 && end_arc < -90) || ...
        (begin_arc < -90 && end_arc >-90) 
         arc(x,y, begin_arc, -90.1)
         arc(x,y,-89.9,end_arc)
        return 
     end
    

    % some data
     xyoff=[x,y];
     ba= begin_arc+90; % degrees
     ea= end_arc+90;
     
     
     r=2;
     res=1; % resolution
    % the engine
     be=sort(mod([ba,ea],360));
     v=be(1):res:be(2);
     line([x, x+r*cosd(v(1))], [y, y+r*sind(v(1))])
     line([x, x+r*cosd(v(length(v)))], [y, y+ r*sind(v(length(v)))]);
     line(xyoff(1)+r*cosd(v),xyoff(2)+r*sind(v),...
          'marker','.',...
          'markersize',3,...
          'color',[1,0,0]);
    % ...embedded
     %line(xyoff(1)+r*cosd(1:360),xyoff(2)+r*sind(1:360),...
     %     'marker','none',...
     %     'color',[1,1,1]);
     %set(gca,'xlim',[-20,20]);
     axis image;

end
